package edu.ntu.cloudroid.xacml.obligation;

import java.net.URI;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;


import com.sun.xacml.Obligation;
import com.sun.xacml.attr.BooleanAttribute;
import com.sun.xacml.attr.DoubleAttribute;
import com.sun.xacml.attr.IntegerAttribute;
import com.sun.xacml.attr.StringAttribute;
import com.sun.xacml.ctx.Attribute;
import com.sun.xacml.ctx.RequestCtx;
import com.sun.xacml.ctx.Subject;

import edu.ntu.cloudroid.model.IDs;
import edu.ntu.cloudroid.model.data.AbstractData;
import edu.ntu.cloudroid.model.data.DetachedData;
import edu.ntu.cloudroid.model.data.LocationData;
import edu.ntu.cloudroid.model.data.VitalSignData;
import edu.ntu.cloudroid.model.data.VitalSignInfo;
import edu.ntu.cloudroid.model.function.stats.IDataStats;
import edu.ntu.cloudroid.model.policy.SimpleFiltering;
import edu.ntu.cloudroid.model.profile.ProfileData;
import edu.ntu.cloudroid.server.backendservice.DataService;
import edu.ntu.cloudroid.server.backendservice.FriendService;
import edu.ntu.cloudroid.xacml.Utilities;
import edu.ntu.cloudroid.xacml.XACMLException;
import edu.ntu.cloudroid.xacml.XACMLStrings;

/**
 * Granularity transformation
 */
public class GranularityObligation implements ObligationHandle {

	@Override
	public List<DetachedData> processObligation(ProfileData subject,
			ProfileData resource, RequestCtx requestCtx, Obligation o)
			throws Exception {
		List<Attribute> assignments = o.getAssignments();
		int granularity=0, colIdx=0;		
		boolean isLatest = false;
		
		for (Attribute a : assignments) {
			if (a.getId().equals(new URI(XACMLStrings.ATTR_Granularity))) {
				IntegerAttribute attr = (IntegerAttribute) a.getValue();
				granularity = (int) attr.getValue();
			}
			if (a.getId()
					.equals(new URI(XACMLStrings.ATTR_Filtering_ColumnIdx))) {
				IntegerAttribute attr = (IntegerAttribute) a.getValue();
				colIdx = (int) attr.getValue();
			}
			if (a.getId()
					.equals(new URI(XACMLStrings.ATTR_GetLatest))) {
				BooleanAttribute attr = (BooleanAttribute) a.getValue();
				isLatest = attr.getValue();
			}
		}
		return this.evaluateStats(subject, resource, requestCtx, colIdx,
				granularity, isLatest);
	}

	private List<DetachedData> evaluateStats(ProfileData subject,
			ProfileData resource, RequestCtx requestCtx, int colIdx,
			int granularity, boolean isLatest) throws Exception {
		List<DetachedData> list = new ArrayList<DetachedData>();
		List<AbstractData> allData = new ArrayList<AbstractData>();
		Date latestTimestamp = FriendService.getFriendTimeStamp(resource.getEmailAddress(), subject.getEmailAddress());
				
		if (!isLatest)				
			allData = DataService.getData(resource, latestTimestamp,
					resource.getDataId());		
		else{
			AbstractData ad = DataService.getLatestData(resource, resource.getDataId());
			if (ad.getTimestamp().after(latestTimestamp))
				allData.add(ad);			
		}
				
		if (allData.size() > 0)
			FriendService.delayTimestampUpdate(resource.getEmailAddress(),
					subject.getEmailAddress(), allData.get(allData.size() - 1)
							.getTimestamp());
		
		for (AbstractData ad : allData)
			list.add((DetachedData)ad.changeGranuality(granularity, colIdx));			
		return list;
	}	
}
